package com.controller;

import java.util.*;
import javax.servlet.http.HttpServletRequest;

import com.Producer.MailMessageProducer;
import com.Producer.RedisCacheProducer;
import com.alibaba.fastjson.JSONObject;
import com.annotation.IgnoreAuth;
import com.constant.AuthConstant;
import com.constant.DBTableNameConstant;
import com.domain.dto.MaintenanceManDTO;
import com.domain.dto.SendCodeDTO;
import com.domain.dto.TokenRedisDTO;
import com.domain.entity.TokenEntity;
import com.exception.ErrorCode.AuthErrorCode;
import com.exception.ErrorCode.UserErrorCode;
import com.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.mapper.EntityWrapper;

import com.domain.entity.WeixiuyuanEntity;

import com.service.WeixiuyuanService;
import com.service.TokenService;


@Slf4j
@RestController
@RequestMapping("/weixiuyuan")
public class WeixiuyuanController {
    @Autowired
    private WeixiuyuanService weixiuyuanService;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisCacheProducer redisCacheProducer;

    @Autowired
    private MailUtils mailUtils;

    @Autowired
    private MailMessageProducer mailMessageProducer;

    /**
     * 登录
     */
	@IgnoreAuth
    @RequestMapping(value = "/login")
    public R login(String username, String password) {
        WeixiuyuanEntity maintenanceMan = weixiuyuanService.selectOne(new EntityWrapper<WeixiuyuanEntity>().eq("username", username));
        //用户是否存在
        if (maintenanceMan == null) {
            return R.error(AuthErrorCode.USER_NOT_EXIST.getMessage());
        }

        //判断密码是否正确
        String salt = maintenanceMan.getSalt();
        String passwordHash = maintenanceMan.getPasswordHash();
        String NowPasswordHash = PasswordEncryptorUtil.encryptPassword(password, Base64.getDecoder().decode(salt));
        if (!passwordHash.equals(NowPasswordHash)) {
            return R.error(AuthErrorCode.USER_PASSWORD_ERROR.getMessage());
        }

        //生成token
        String token = JJwtUtils.createToken(maintenanceMan);

        //将token存入到数据库中
        tokenService.insertToken(maintenanceMan.getId(), username, "weixiuyuan", maintenanceMan.getRole(), token);
        log.info("维修员用户：{}登录成功", username);
        log.info("生成令牌：{}", token);

        return R.ok().put("token", token);
    }

    /**
     * 获取维修员个人信息
     */
    @RequestMapping("/session")
    public R getCurrUser(HttpServletRequest request) {
        //从redis中获取用户信息
        String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
        String jsonInfo = redisClient.getString(AuthConstant.tokenPrefix + token);
        String userid = JSONObject.parseObject(jsonInfo, TokenRedisDTO.class).getUserid();
        String json = redisClient.getString(AuthConstant.MAINTENANCEMAN_INFO_KEY + userid);
        if (StringUtils.isNotEmpty(json)) {
            WeixiuyuanEntity maintenanceMan = JSONObject.parseObject(json, WeixiuyuanEntity.class);
            //将数据返回给前端
            return R.ok().put("data", maintenanceMan);
        }

        //为空的话查询数据库
        WeixiuyuanEntity maintenanceMan = weixiuyuanService.selectOne(new EntityWrapper<WeixiuyuanEntity>().eq("id", userid));
        MaintenanceManDTO maintenanceManDTO = new MaintenanceManDTO();
        BeanUtils.copyProperties(maintenanceMan, maintenanceManDTO);
        String jsonString = JSONObject.toJSONString(maintenanceManDTO);

        //将查询到的结果返回并且将结果存入到redis中
        redisCacheProducer.maintenanceManSendToKafka(maintenanceMan.getId().toString(), jsonString);

        return R.ok().put("data", maintenanceMan);

    }

    /**
     * 修改维修员密码
     */
    @PostMapping("/updatePassword")
    public R updatePassword(@RequestBody SendCodeDTO sendCodeDTO, HttpServletRequest request) {
        String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);

        TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(redisClient.getString(AuthConstant.tokenPrefix + token), TokenRedisDTO.class);

        //先判断验证码是否正确
        String redisCode = redisClient.getString(AuthConstant.MAINTENANCEMAN_INFO_CAPTCHA_PREFIX + tokenRedisDTO.getUserid());

        if (!sendCodeDTO.getCode().equals(redisCode)) {
            return R.error(422, UserErrorCode.CAPTCHA_CODE_INCORRECT.getMessage());
        }

        byte[] salt = PasswordEncryptorUtil.getSalt();
        String encryptPassword = PasswordEncryptorUtil.encryptPassword(sendCodeDTO.getNewPassword(), salt);

        WeixiuyuanEntity maintenanceMan = new WeixiuyuanEntity();
        maintenanceMan.setSalt(Base64.getEncoder().encodeToString(salt));
        maintenanceMan.setPasswordHash(encryptPassword);
        maintenanceMan.setId(Long.valueOf(tokenRedisDTO.getUserid()));

        //将盐和密码存入到数据库中
        weixiuyuanService.updateById(maintenanceMan);

        //删掉redis中验证码缓存
        redisClient.deleteKey(AuthConstant.MAINTENANCEMAN_INFO_CAPTCHA_PREFIX + tokenRedisDTO.getUserid());

        return R.ok();
    }


    /**
     * 发送验证码
     */
    @GetMapping("/sendCode")
    public R sendCode(HttpServletRequest request) {

        String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);

        TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(redisClient.getString(AuthConstant.tokenPrefix + token), TokenRedisDTO.class);

        WeixiuyuanEntity maintenanceMan = JSONObject.parseObject(redisClient.getString(AuthConstant.MAINTENANCEMAN_INFO_KEY + tokenRedisDTO.getUserid()), WeixiuyuanEntity.class);

        //生成验证码
        String code = CaptchaUtil.generateCaptcha();

        //生成后将验证码存放到redis中有效器为15分钟
        redisClient.setMinString(AuthConstant.MAINTENANCEMAN_INFO_CAPTCHA_PREFIX + maintenanceMan.getId(), code, 900L);

        String content = "[汽车充电桩管理系统]" + code + " 是你修改密码所需的验证码，不要和其他人分享，有效期为15分钟";

        mailUtils.sendMail(maintenanceMan.getEmail(), "汽车充电桩管理系统，用于修改密码所需的验证码", content);

        return R.ok();
    }


    /**
     * 修改维修员信息
     */
    @PostMapping("/updateInfo")
    public R updateInfo(@RequestBody MaintenanceManDTO maintenanceManDTO, HttpServletRequest request) {
        String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
        String tokenJson = redisClient.getString(AuthConstant.tokenPrefix + token);
        TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(tokenJson, TokenRedisDTO.class);

        //直接修改数据库中数据
        WeixiuyuanEntity maintenanceMan = new WeixiuyuanEntity();
        BeanUtils.copyProperties(maintenanceManDTO, maintenanceMan);

        weixiuyuanService.updateByJobNumber(maintenanceManDTO, tokenRedisDTO.getUserid());

        return R.ok();

    }


    /**
     * 退出登录
     */
    @DeleteMapping("/logout")
    public R logout(HttpServletRequest request) {
        String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
        String jsonInfo = redisClient.getString(AuthConstant.tokenPrefix + token);
        String userid = JSONObject.parseObject(jsonInfo, TokenRedisDTO.class).getUserid();
        //删除掉数据库中的数据
        tokenService.delete(new EntityWrapper<TokenEntity>().eq("userid", userid));

        return R.ok("退出成功");
    }

    /**
     * 管理员维修员管理
     */
    @GetMapping("/page")
    public R page(@RequestParam int pageNum,@RequestParam int pageSize,WeixiuyuanEntity weixiuyuan) {
        PageUtils page = weixiuyuanService.queryPage(pageNum,pageSize,weixiuyuan);

        return R.ok().put("data", page);
    }

    /**
     * 管理员查看维修员详情
     */
    @GetMapping("/info/{id}")
    public R info(@PathVariable("id") Long id) {

        String json = redisClient.getString(AuthConstant.MAINTENANCEMAN_INFO_KEY + id);
        if (StringUtils.isNotEmpty(json)) {
            WeixiuyuanEntity entity = JSONObject.parseObject(json, WeixiuyuanEntity.class);
            return R.ok().put("data", entity);
        }

        WeixiuyuanEntity entity = weixiuyuanService.selectById(id);

        if (entity != null) {
            redisClient.setMinString(AuthConstant.MAINTENANCEMAN_INFO_KEY + id, JSONObject.toJSONString(entity), 2000L);
        }

        return R.ok().put("data", entity);

    }

    /**
     * 管理员修改维修员信息
     */
    @PostMapping("/update")
    public R update(@RequestBody MaintenanceManDTO maintenanceManDTO) {


        WeixiuyuanEntity entity = new WeixiuyuanEntity();
        BeanUtils.copyProperties(maintenanceManDTO, entity);
        weixiuyuanService.updateById(entity);
        return R.ok();

    }

    /**
     * 管理员删除维修员信息
     */
    @PostMapping("/delete")
    public R delete(@RequestBody Long[] ids) {
        weixiuyuanService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }

    /**
     * 管理员新增维修员信息
     */
    @PostMapping("/save")
    public R save(@RequestBody WeixiuyuanEntity weixiuyuan) {
        weixiuyuan.setId(new Date().getTime() + new Double(Math.floor(Math.random() * 1000)).longValue());

        WeixiuyuanEntity user = weixiuyuanService.selectOne(new EntityWrapper<WeixiuyuanEntity>()
                .eq("job_number", weixiuyuan.getJobNumber())
                .or()
                .eq("username",weixiuyuan.getUsername()));
        if (user != null) {
            return R.error(AuthErrorCode.USER_IS_EXIST.getMessage());
        }

        //维修员默认密码
        String password = weixiuyuan.getUsername() + weixiuyuan.getJobNumber();
        byte[] salt = PasswordEncryptorUtil.getSalt();
        String encryptPassword = PasswordEncryptorUtil.encryptPassword(password, salt);
        weixiuyuan.setPasswordHash(encryptPassword);
        weixiuyuan.setSalt(Base64.getEncoder().encodeToString(salt));
        weixiuyuan.setRole(DBTableNameConstant.MAINTENANCEMAN_NAME);

        weixiuyuanService.insert(weixiuyuan);

        //往kafka发送一条msg告诉维修员的初始密码
        mailMessageProducer.sendMailMsgToKafka(weixiuyuan.getEmail(),password);

        return R.ok();
    }

}
